package stream._03midoperations;

import org.junit.Test;
import stream.bean.Student;
import stream.bean.StudentList;

import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class StreamMidOperationTest {
    /*
    filter方法
    用于通过设置的条件过滤元素
    使用场景：
        对元素进行过滤，比如想要年龄大于20的学生
     */
   @Test
    public void testFilter() {
       List<Student> studentList = new StudentList().studentList;

       //中间操作过滤
       List<Student> list = studentList.stream().filter(new Predicate<Student>() {
           @Override
           public boolean test(Student student) {
               return student.getAddress() == Student.Address.BJ;
           }
       }).collect(Collectors.toList());

       System.out.println(list);
       System.out.println(list.size());

   }

    @Test
    public void testFilter2() {
       List<Student> studentList = new StudentList().studentList;
       List<Student> list = studentList.stream().filter(student ->
               student.getAddress() == Student.Address.BJ).collect(Collectors.toList());//终止操作
    }
    /*
    distinct方法用于筛选元素(相当于去除重复元素)
        使用场景：
        - 对元素进行去重处理。底层是`LinkedHashSet`
        所以需要注意：如果使用自定义的类，调用distinct，需要重写hashCode和equals方法
     */
    @Test
    public void testDistinct() {
        List<Student> studentList =
                new StudentList().studentList;
        List<Student> list = studentList.stream().filter(
                student -> student.getAddress() == Student.Address.BJ
        ).distinct()//去重
                .collect(Collectors.toList());
    }
    /*
    limit 方法用于获取指定数量(最大)的流。
    // Stream<T> limit(long maxSize);
    // limit(n)方法, 返回前n个元素.
    // 如果流中有10个元素，limit(3) 则只返回3个元素。
    // 如果流中有1个元素，limit(3) 则只返回1个元素。
     一般结合排序sort
     */
    @Test
    public void testLimit() {
        List<Student> studentList =
                new StudentList().studentList;
        List<Student> list = studentList.stream().filter(
                student -> student.getAddress() == Student.Address.BJ
        ).distinct()//去重
                .limit(3).
                collect(Collectors.toList());
        list.forEach(student -> System.out.println(list));
        System.out.println(list.size());
    }
    /*
    // Stream<T> skip(long n);
    // skip(n)方法, 跳过前n个元素, 返回之后的元素.  (如果整体不够n个, 返回空流)
     */
    @Test
    public void testSkip() {
        List<Student> studentList =
                new StudentList().studentList;
        List<Student> list = studentList.stream()
                .filter(student -> student.getAddress() == Student.Address.BJ)
                .skip(6)
                .collect(Collectors.toList());
        list.forEach(student -> System.out.println(list));
    }
    /*
    map 方法用于映射每个元素到对应的结果。
    从一个类型转换到另外一种类型。或者不变化类型
    使用场景：
    输入的是一个类型，希望以另外一个类型输出。
      - 比如我想将一批人的年龄，转化为 青年（0-29），中青年（30-39），中年（40-49），中老年（50岁以上）。
      - 比如我想获取班里每个同学的姓名
      - 获取每个同学的姓氏
     */
    @Test
    public void testMap() {
        List<Student> studentList =
                new StudentList().studentList;
        List<String> list = studentList.stream()
                .filter(student -> student.getAddress() == Student.Address.BJ)
                .map(new Function<Student, String>() {
                    @Override
                    public String apply(Student student) {
                        //返回学生名字
                        //Student ----> String
                        return student.getName();
                    }
                }).collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println(list.size());
    }

    @Test
    public void testMap2() {
        List<Student> studentList =
                new StudentList().studentList;
        List<String> list = studentList.stream()
                .filter(student -> student.getAddress() == Student.Address.BJ)
                .map(student -> student.getName())
                .map(s -> s.substring(0,1))
                .distinct()//去重
                .collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println(list.size());
    }


}
